#include "selectclass.h"
#include "ui_selectclass.h"
LinkTrie R=NULL;
QString number="";

//这个选课退课界面的左下角，是所输入学号的那个人的没有得到考试成绩的信息
//即已经修过的课在寒假暑假都已经录入过考试成绩了，而这学期要修的课是已经选了，但没有录入过成绩的课

SelectClass::SelectClass(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::SelectClass)
{
    ui->setupUi(this);
    setWindowFlags(Qt::Widget);//使dialog项目有最大最小化按钮

    //这块把学生学号导入trie树，以及隐藏listWidget
    R=create();
    QSqlQuery query;
    QString str1;
    query.exec("select * from student");
    while(query.next())
    {
        str1 = query.value("学号").toString();
        char* ch;
        QByteArray ba = str1.toLatin1();
        ch=ba.data();
        if(isNumber(ch))
        {
            insert(R,ch);
        }
        else
        {
            continue;
        }
    }
    ui->listWidget->hide();

    //这块是右上角那个选课查询的文本框的模糊搜索
    QStringList wordList;
    wordList<<"计算机科学导论"<<"高级语言程序设计"<<"概率论"<<"面向对象程序设计"
           <<"离散结构"<<"数据结构"<<"高等数学1"<<"高等数学2"<<"大学数学"
          <<"应用文写作"<<"近现代史纲要"<<"军事理论"<<"数字电路与逻辑设计"
         <<"软件工程"<<"操作系统"<<"计算智能"<<"思想修养与法律基础"
        <<"大学物理"<<"大学语文"<<"大学英语1"<<"大学英语2"<<"大学英语3"
       <<"大学英语4"<<"植物学"<<"A系列"<<"C语言程序设计"<<"无机化学";
    QCompleter *completer = new QCompleter(wordList, this);
    ui->courseName->setCompleter(completer);

    //这块是选课部分，对数据库中course表的模型和视图
    modelSelectClass = new QSqlTableModel(this);
    modelSelectClass->setTable("course");//指定使用哪个表
    //把model放在view
    this->ui->viewSelectClass->setModel(modelSelectClass);
    //列宽随窗口大小改变而改变，每列平均分配，充满整个表，但是此时列宽不能拖动进行改变
    ui->viewSelectClass->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
    //显示model里的数据
    modelSelectClass->select();
    //QSqlTableModel默认是可读写的模型，该语句从视图进行设置，使其成为只读模型
    this->ui->viewSelectClass->setEditTriggers(QAbstractItemView::NoEditTriggers);
    //一次选中一行
    ui->viewSelectClass->setSelectionBehavior(QAbstractItemView::SelectRows);

    //这块是我已选的课程的信息部分，对数据库中chooseCourse表的模型和视图
    modelMyClass = new QSqlTableModel(this);
    modelMyClass->setTable("chooseCourse");//指定使用哪个表
    //把model放在view
    this->ui->viewMyClass->setModel(modelMyClass);
    //列宽随窗口大小改变而改变，每列平均分配，充满整个表，但是此时列宽不能拖动进行改变
    ui->viewMyClass->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
    //设置model的编辑模式，手动提交修改
    modelMyClass->setEditStrategy(QSqlTableModel::OnManualSubmit);
    //一次选中一行
    ui->viewMyClass->setSelectionBehavior(QAbstractItemView::SelectRows);
    //把不需要显示的列隐藏
    ui->viewMyClass->setColumnHidden(2,true);
    ui->viewMyClass->setColumnHidden(3,true);
    ui->viewMyClass->setColumnHidden(5,true);

}

bool SelectClass::isNumber(char* str)
{
    while(*str && *str>='0' && *str<='9') str++;
    //c语言，0是假，非0是真
    //'\0'ascii码是0
    if (*str)//看看有没有到字符串末尾'\0'处
    { //不是纯数字
        return false;
    }
    else
    { //纯数字
        return true;
    }
}

//新建并初始化一个节点
LinkTrie SelectClass::create()
{
    LinkTrie treeNode;
    treeNode = (LinkTrie)malloc(sizeof(TrieNode));//malloc分配失败返回null
    if(treeNode == NULL)
    {
        QMessageBox::information(NULL, "提示", "分配空间失败。", QMessageBox::Ok);
        return NULL;
    }
    /*初始化*/
    memset(treeNode->next, 0x00, sizeof(treeNode->next));
    //上面这句话去掉后，会导致销毁这棵树的时候，R->next[i]！=NULL，程序运行不下去
    treeNode->cnt = 0;
    return treeNode;
}

//插入一个学号
int SelectClass::insert(LinkTrie R, char* str)
{
    int i, index;
    LinkTrie tempNode = R;

    if(R==NULL || str == NULL || str[0]=='\0')
        return 0;

    for(i=0;i<strlen(str);i++)
    {
        index = str[i]-'0';
        if(tempNode->next[index] != NULL)
        {
            tempNode  = tempNode->next[index];
            continue;
        }
        tempNode->next[index] = create();
        if(tempNode->next[index] == NULL)
        {
            QMessageBox::information(NULL, "提示", "分配空间失败。", QMessageBox::Ok);
            return -1;
        }
        tempNode  = tempNode->next[index];
    }
    tempNode->cnt = tempNode->cnt + 1;
    return 0;
}

//这个函数没有用到//销毁Trie树
void SelectClass::destroy(LinkTrie R)
{
    int i;
    for(i=0; i<10; i++)
    {
        if(R->next[i] != NULL)
        {
            destroy(R->next[i]);
        }
    }
    free(R); /*子节点全部删除后才可以释放根节点*/
    R = NULL;//free以后，只是把指针指向的空间清空，指针本身仍指向那块内存，所以需要使指针指向null
    return;
}

//输入前缀，输出所有是这个前缀的单词
void SelectClass::prefix(LinkTrie R,char* word)
{
    int i, index;
    LinkTrie tempNode = R;
    if(word == NULL||word[0]=='\0')
    {
        return;
    }
    for(i=0;i<strlen(word);i++)
    {
        index = word[i]-'0';
        if(tempNode->next[index] == NULL)
        {
            return;
        }
        tempNode  = tempNode->next[index];
    }
    int j=strlen(word);
    if(tempNode->cnt > 0)
    {
        ui->listWidget->addItem(QString("%1").arg(word));
    }
    prefixTraverse(tempNode,word,j);
    return;
}

//被Prefix()函数调用
void SelectClass::prefixTraverse(LinkTrie tempNode,char* str,int j)
{
    int i;
    fflush(stdin);
    for(i=0; i<10; i++)
    {
        if(tempNode->next[i] == NULL)
        {
            continue;
        }

        str[j] = i+'0';
        j++;
        if(tempNode->next[i]->cnt > 0)
        {
            str[j] = '\0';
            ui->listWidget->addItem(QString("%1").arg(str));
        }
        prefixTraverse(tempNode->next[i],str,j);
        j--;
    }
    return;
}

SelectClass::~SelectClass()
{
    delete ui;
}

void SelectClass::on_number_textChanged(const QString &arg1)
{
    this->ui->listWidget->clear();
    this->ui->listWidget->show();
    char* ch;
    QByteArray ba = arg1.toLatin1();
    ch=ba.data();
    if(isNumber(ch))
    {
        prefix(R,ch);
    }
    else
    {
        QMessageBox::information(NULL, "提示", "学号必须为数字！", QMessageBox::Ok);
    }
}

void SelectClass::on_listWidget_itemClicked(QListWidgetItem *item)
{
    QString clickItem=item->text();
    this->ui->number->setText(clickItem);
    this->ui->listWidget->hide();
}

void SelectClass::on_selectClass_clicked()
{
    if(number=="")
    {
        QMessageBox::information(NULL, "提示", "请先输入学号！", QMessageBox::Ok);
    }
    else
    {
        QModelIndex index=ui->viewSelectClass->currentIndex();//得到点击的项的索引
        QSqlRecord record = modelSelectClass->record(index.row());//index.row()，得到点击的项的行数。这整句话是取出这一条点击的记录
        QString courseId = record.value("课程编号").toString();
        QString courseName =record.value("课程名称").toString();
        QString courseCredit = record.value("课程学分").toString();

        QSqlQuery query;
        bool judge=query.exec("INSERT INTO chooseCourse (修读学生的学号,课程名称,课程编号,课程学分) VALUES('"+number+"','"+courseName+"','"+courseId+"','"+courseCredit+"')");
        if(judge==true)
        {
            QMessageBox::information(NULL, "提示", QString("%1\n选课成功！").arg(courseName), QMessageBox::Ok);
            modelMyClass->select();
        }
        else
        {
            QMessageBox::information(NULL, "提示", "选课不成功！", QMessageBox::Ok);
            //qDebug()<<query.lastError().text()<<endl;
        }
    }
}

void SelectClass::on_number_editingFinished()
{
    this->ui->listWidget->hide();
}

void SelectClass::on_sure_clicked()
{
    number=this->ui->number->text();
    modelMyClass->setFilter(QString("修读学生的学号='%1'and 考试成绩 IS NULL").arg(number));//setFilter里面放一个sql子句，QString和arg是返回一个字符串
    modelMyClass->select();
}

void SelectClass::on_pushButton_clicked()
{
    QString courseName= this->ui->courseName->text();
    modelSelectClass->setFilter(QString("课程名称='%1'").arg(courseName));
}

void SelectClass::on_deleteClass_clicked()
{
    QModelIndex index=ui->viewMyClass->currentIndex();
    QSqlRecord record = modelMyClass->record(index.row());
    QString courseName =record.value("课程名称").toString();
    //获取选中的模型
    QItemSelectionModel *sModel =ui->viewMyClass->selectionModel();
    //取出模型中的索引  //选中了几行，就有几个索引
    QModelIndexList list = sModel->selectedRows();
    //删除所有选中的行
    for(int i = 0; i < list.size(); i++)//list.size()得到索引数目
    {
        modelMyClass->removeRow(list.at(i).row());//list.at(i)即第i个索引，row()得到这个索引中的行号
    }
    modelMyClass->submitAll(); //提交动作
    modelMyClass->select();
    QMessageBox::information(NULL, "提示", QString("%1\n退选成功！").arg(courseName), QMessageBox::Ok);
}
